<template>
  <div id="map" class="map-container">
    <div class="map-controls">
      <div class="base-layer-switcher">
        <button :class="['control-btn', activeBaseLayer === 'vector' ? 'active' : '']"
          @click="switchTiandituBaseLayer('vector')">
          矢量图
        </button>
        <button :class="['control-btn', activeBaseLayer === 'image' ? 'active' : '']"
          @click="switchTiandituBaseLayer('image')">
          影像图
        </button>
      </div>
    </div>
    <MapPopup :map-box="map" v-show="popupVisible" :feature-data="popupFeatureData" :layer-id="popupLayerId"
      :position="popupPosition" @close="closePopup" />

    <!-- 右侧弹窗面板 -->
    <RightPanel :visible="panelVisible" :title="panelTitle" :panel-layers="activePanelLayers"
      :active-layer-id="activePanelLayer" @close="closePanel" @switch-layer="switchPanelLayer">
      <WaterQualityPanel @close="closePanel" v-if="activePanelLayer === 'zidongzhan'" />
      <ShougongduanmianPanel v-if="activePanelLayer === 'shougongduanmian'" />
      <PollutionSourcePanel v-if="activePanelLayer === 'wuranyuan'" />
      <shuiyuandiPanel v-if="activePanelLayer === 'shuiyuandi'" />
      <RehupaiwukouPanel v-if="activePanelLayer === 'ruhepaiwukou'" />
      <yujingPanel ref="yujingPanelRef" v-if="activePanelLayer === 'yujing'" @showPointDetails="showPointDetails"
        @queryYujingData="queryYujingData" />

      <wuranyuankuosanSidebar v-if="activePanelLayer === 'wuranyuankuosan'" @close="closePanel"
        :current-time="currentTime" :pollution-location="pickedCoordinates" :is-animating="isAnimating"
        :is-paused="isPaused" :parent-progress="animationProgressPercent" @river-change="addRiverToMap"
        @pick-location="onPickLocation" @start-simulation="handleStartSimulation" @pause-simulation="pauseSimulation"
        @resume-simulation="resumeSimulation" @reset-simulation="resetSimulation" />
    </RightPanel>
  </div>
</template>

<script>
import 'ol/ol.css';
import { Map as olMap, View } from 'ol';
import TileLayer from 'ol/layer/Tile';
import { XYZ } from 'ol/source';
import WMTSTileGrid from 'ol/tilegrid/WMTS';
import { defaults as defaultControls } from 'ol/control';
import 'ol/proj/epsg4326';

import VectorLayer from 'ol/layer/Vector';
import VectorSource from 'ol/source/Vector';
import { GeoJSON } from 'ol/format';
import { Style, Stroke, Fill, Circle } from 'ol/style';
import Feature from 'ol/Feature';
import Point from 'ol/geom/Point';

import chroma from 'chroma-js';

import { wmsBaseUrl } from '@/views/biz/utils/config';
import {
  createPointLayer,
  createHeatmapLayer,
  createWmsLayer,
  removeLayerById,
} from '@/views/biz/utils/layerLoader';
import { getData } from '@/views/biz/utils/getData';

import MapPopup from './MapPopup.vue';
import RightPanel from './RightPanel.vue';
import WaterQualityPanel from './panel/WaterQualityPanel.vue';
import ShougongduanmianPanel from './panel/ShougongduanmianPanel.vue';
import PollutionSourcePanel from './panel/PollutionSourcePanel.vue';
import shuiyuandiPanel from './panel/shuiyuandiPanel.vue';
import RehupaiwukouPanel from './panel/RehupaiwukouPanel.vue';
import yujingPanel from './panel/yujingPanel.vue';
import wuranyuankuosanSidebar from './panel/wuranyuankuosanSidebar.vue';
// 地图配置常量
const MAP_CONFIG = {
  DEFAULT_CENTER: [112.930691, 35.791355],
  DEFAULT_ZOOM: 11,
  MAX_ZOOM: 18,
  MIN_ZOOM: 1,
  PROJECTION: 'EPSG:4326'
};

// 天地图配置常量
const TIANDITU_CONFIG = {
  TOKEN: '3d9e801ed2c10bc2e6eba8037e53817b',
  TILE_GRID: new WMTSTileGrid({
    origin: [-180, 90],
    resolutions: [1.40625, 0.703125, 0.3515625, 0.17578125, 0.087890625, 0.0439453125, 0.02197265625, 0.010986328125, 0.0054931640625, 0.00274658203125, 0.001373291015625, 0.0006866455078125, 0.00034332275390625, 0.000171661376953125, 0.0000858306884765625],
    matrixIds: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15']
  })
};

// 面板图层映射配置
const PANEL_LAYER_CONFIG = {
  WATER_QUALITY: ['guokongzhan', 'shengkongzhan', 'shikongzhan', 'xiankongzhan'],
  MANUAL_SECTION: ['shougongduanmian'],
  WATER_SOURCE: ['qushuikou', 'shuiyuandiStation'],
  POLLUTION_SOURCE: ['wuranyuan'],
  RIVER_DISCHARGE: ['ruhepaiwukou'],
  WARNING: ['yujing'],
  PANEL_LAYER_IDS: ['zidongzhan', 'wuranyuan', 'shuiyuandi', 'shougongduanmian', 'ruhepaiwukou', 'yujing'],
  WRYKS: ["wuranyuankuosan"]
};

export default {
  name: 'MapContainer',
  components: {
    MapPopup,
    RightPanel,
    WaterQualityPanel,
    ShougongduanmianPanel,
    PollutionSourcePanel,
    shuiyuandiPanel,
    RehupaiwukouPanel,
    yujingPanel,
    wuranyuankuosanSidebar
  },

  props: {
    /** 地图图层配置数组 */
    layers: {
      type: Array,
      default: () => []
    },

    /** 当前激活的图层对象 */
    currentActiveLayer: {
      type: Object,
      default: null
    },

    /** 面板显示状态 */
    showPanel: {
      type: Boolean,
      default: true
    },

    /** 面板内容配置 */
    panelContent: {
      type: Object,
      default: () => { }
    }
  },

  data() {
    return {
      /** 地图实例 */
      map: null,

      /** 地图视图实例 */
      view: null,

      /** 地图覆盖物 */
      mapOverlay: null,

      /** 已加载的图层对象映射表 */
      loadedLayers: {},

      /** 当前已加载的图层ID列表 */
      currentLayerIds: [],

      /** 弹窗相关数据 */
      popupVisible: false,
      popupFeatureData: {},
      popupLayerId: '',
      popupPosition: [0, 0],

      /** 右侧面板相关数据 */
      panelVisible: false,
      panelTitle: '图层信息',
      activePanelLayer: '',
      activePanelLayers: [],

      /** 激活的底图层类型 */
      activeBaseLayer: 'vector', // 'vector' 或 'image'

      /** 面板打开状态 */
      isPanelOpen: this.showPanel,

      /** 污染源扩散 */
      riverLayer: null,
      markerLayer: null,
      // pollutionMarker: null,
      // 全局变量

      pollutedLocation: [],
      isPickingLocation: false,
      pickedCoordinates: null,    // 已拾


      currentTime: 0,
      SelectdRiver: '巴公河', // 默认选择的河流

      emission: 7200, // kg
      pollution_rate: 1, // kg/s
      total_time: 2, // h (小时)
      flow_speed: 0.5, // m/s
      timestep: 5, // min (分钟)
      // 动画控制
      animationTimer: null,
      animationStepInterval: 300, // ms, 每个模拟时间步的动画间隔（可调）
      styleCache: {},
      // 动画状态
      isAnimating: false,
      isPaused: false,
      animationCurrentStep: 0,
      animationTotalSteps: 0,
      animationFeatureMap: null,
      animationStartIndex: null,
      animationMaxAffectedIndex: null,
      animationReleaseTime: 0,
      animationFeatures: null,
      animationTimeStepSeconds: 0,
      animationPollutionRate: 0,
      animationFlowSpeed: 0,
      animationProgressPercent: 0,
      animationTotalSimSeconds: 0,
    };
  },

  computed: {
    /** 判断当前是否应该显示水质面板（多个自动站图层共用） */
    isWaterQualityPanel() {
      const waterQualityLayerIds = ['guokongzhan', 'shengkongzhan', 'shikongzhan', 'xiankongzhan', 'shougongduanmian'];
      return waterQualityLayerIds.includes(this.activePanelLayer);
    },

    /** 右侧面板组件的props */
    panelProps() {
      return {
        map: this.map,
        view: this.view,
        activeLayer: this.currentActiveLayer,
        show: this.isPanelOpen
      };
    }
  },
  mounted() {
    // 初始化地图
    this.initMap();
    this.initPollutionColors();

    // 等待DOM更新后加载图层
    this.$nextTick(() => {
      this.updateLayers(this.layers, this.currentActiveLayer);
    });

    // 添加窗口大小变化监听
    window.addEventListener('resize', this.handleResize);
  },

  beforeDestroy() {
    // 移除事件监听
    window.removeEventListener('resize', this.handleResize);

    // 销毁地图实例
    if (this.map) {
      this.map.dispose();
    }
  },
  methods: {


    showPointDetails(point) {
      if (!point.longitude || !point.latitude) {
        this.$notify.error({
          title: '错误',
          message: '点位坐标无效',
          duration: 2000
        });
        return;
      }
      let coordinate = [point.longitude, point.latitude]
      this.map.getView().setCenter(coordinate);
    },
    initMap() {
      // 创建WMS基础图层
      const base_layer = this.createBaseWmsLayer('base_dlg', 'gp:base_dlg', true);
      const base_img = this.createBaseWmsLayer('base_img', 'gp:base_img', false);

      // 创建天地图图层
      const tianditu_layers = this.createTiandituLayers();

      this.map = new olMap({
        target: 'map',
        controls: defaultControls({ zoom: false }),
        layers: [
          ...tianditu_layers,
          base_layer,
          base_img
        ],
        view: new View({
          projection: MAP_CONFIG.PROJECTION,
          center: MAP_CONFIG.DEFAULT_CENTER,
          constrainResolution: true,
          zoom: MAP_CONFIG.DEFAULT_ZOOM,
          maxZoom: MAP_CONFIG.MAX_ZOOM,
          minZoom: MAP_CONFIG.MIN_ZOOM
        })
      });
      // 添加点击交互
      this.registerMapClick();
    },

    // 处理窗口大小变化
    handleResize() {
      if (this.map) {
        this.map.updateSize();
      }
    },
    clickpointhandel(feature) {
      const layerId = feature ? feature['layerId'] : '';
      if (layerId === 'yujing') {
        this.$refs.yujingPanelRef.handleTab('detail', feature['pointId'], feature['pointName'])
      }
    },
    registerMapClick() {
      this.map.on('singleclick', (evt) => {
        const coordinate = evt.coordinate;
        const features = [];
        this.map.forEachFeatureAtPixel(evt.pixel, (feature) => {
          features.push(feature);
        });

        // 如果找到了要素，则可以进一步处理
        if (features.length > 0) {
          // 处理获取到的要素
          const feature = features[0];
          // 获取要素属性
          const featureData = feature.getProperties();
          this.clickpointhandel(featureData);

          // 获取图层信息
          const layerId = feature ? feature.get('layerId') : '';

          // 显示弹窗
          this.showPopup(featureData, layerId, coordinate);
        } else {

          this.closePopup();
        }
      });
    },
    /**
     * 更新地图图层
     * 
     * @param {Array} newLayers - 新的图层组数组，每个图层组包含图层信息
     *        每个图层对象应包含id等属性
     */
    async updateLayers(newLayers, currentActiveLayer) {
      // 提取所有新图层的ID
      const newLayerIds = new Set();
      newLayers.forEach(layerGroup => {
        if (layerGroup.layers && Array.isArray(layerGroup.layers)) {
          layerGroup.layers.forEach(layer => {
            newLayerIds.add(layer.id);
          });
        }
      });

      // 移除不再需要的图层
      const layersToRemove = this.currentLayerIds.filter(id => !newLayerIds.has(id));
      layersToRemove.forEach(id => this.removeLayer(id));
      if (this.riverLayer) {
        this.map.removeLayer(this.riverLayer);
      }

      if (this.markerLayer) {
        this.map.removeLayer(this.markerLayer);
      }


      // 添加新图层
      const addLayerPromises = [];
      newLayers.forEach(layerGroup => {
        if (layerGroup.layers && Array.isArray(layerGroup.layers)) {
          layerGroup.layers.forEach(layer => {
            if (!this.currentLayerIds.includes(layer.id)) {
              this.currentLayerIds.push(layer.id);
              const promise = this.createLayer(layer)
                .then((newLayer) => {
                  if (newLayer) {
                    if (layer.id === 'wuranyuankuosan') {
                      console.log("wuranyuankuosan")
                    } else {
                      this.addLayerToMap(newLayer, layer);
                    }


                  }
                })
                .catch((error) => {
                  console.error(`添加图层 ${layer.id} 失败:`, error);
                });
              addLayerPromises.push(promise);
            }
          });
        }
      });

      // 等待所有图层添加完成后处理面板显示逻辑
      try {
        await Promise.all(addLayerPromises);
      } catch (error) {
        console.error('添加图层过程中出现错误:', error);
      } finally {
        this.handlePanelVisibility(newLayers, currentActiveLayer);
      }
    },

    handlePanelVisibility(layers, currentActiveLayer) {
      const panelLayers = new Map();

      // 分类处理不同类型的图层
      layers.forEach(layerGroup => {
        if (layerGroup.layers && Array.isArray(layerGroup.layers)) {
          layerGroup.layers.forEach(layer => {
            if (PANEL_LAYER_CONFIG.WATER_QUALITY.includes(layer.id)) {
              panelLayers.set('zidongzhan', { id: 'zidongzhan', name: '自动站' });
            } else if (PANEL_LAYER_CONFIG.MANUAL_SECTION.includes(layer.id)) {
              panelLayers.set('shougongduanmian', { id: 'shougongduanmian', name: '实验室数据' });
            } else if (PANEL_LAYER_CONFIG.WATER_SOURCE.includes(layer.id)) {
              panelLayers.set('shuiyuandi', { id: 'shuiyuandi', name: '水源地' });
            } else if (PANEL_LAYER_CONFIG.POLLUTION_SOURCE.includes(layer.id)) {
              panelLayers.set('wuranyuan', { id: 'wuranyuan', name: '污染源' });
            } else if (PANEL_LAYER_CONFIG.RIVER_DISCHARGE.includes(layer.id)) {
              panelLayers.set('ruhepaiwukou', { id: 'ruhepaiwukou', name: '入河排污口' });
            } else if (PANEL_LAYER_CONFIG.WARNING.includes(layer.id)) {
              panelLayers.set('yujing', { id: 'yujing', name: '预警' });
            }
            else if (PANEL_LAYER_CONFIG.WRYKS.includes(layer.id)) {
              panelLayers.set('wuranyuankuosan', { id: 'wuranyuankuosan', name: '污染源扩散' });
            }
          });
        }
      });

      // 转换为数组格式
      const panelLayersArray = Array.from(panelLayers.values());
      console.log("panelLayersArray", panelLayersArray);
      this.activePanelLayers = panelLayersArray;

      if (panelLayersArray.length > 0) {
        // 设置当前活动面板图层
        this.activePanelLayer = currentActiveLayer?.id;

        // 如果当前活动图层不在面板图层中，选择最后一个
        if (!this.activePanelLayer || !panelLayers.has(this.activePanelLayer)) {
          const activeLayer = panelLayersArray[panelLayersArray.length - 1];
          this.activePanelLayer = activeLayer.id;
          this.panelTitle = activeLayer.name + '信息';
        } else {
          // 确保panelTitle与当前activePanelLayer保持一致
          const currentLayer = panelLayersArray.find(l => l.id === this.activePanelLayer);
          if (currentLayer) {
            this.panelTitle = currentLayer.name + '信息';
          }
        }
        this.panelVisible = true;
      } else {
        this.closePanel();
      }
    },


    // 切换面板图层
    switchPanelLayer(layer) {
      this.activePanelLayer = layer.id;
      this.panelTitle = layer.name;
    },

    // helper: 根据 id 查找地图图层
    getLayerById(id) {
      return this.map && this.map.getLayers().getArray().find(l => l.get('id') === id);
    },

    // 判断图层是否需要显示面板
    shouldShowPanel(layerId) {
      return PANEL_LAYER_CONFIG.PANEL_LAYER_IDS.includes(layerId);
    },
    async createLayer(layer) {
      try {
        switch (layer.dataType) {
          case 'dataApi':
            const response = await getData(layer.id);
            const data = response.data || [];
            return layer.heatmap
              ? createHeatmapLayer({
                data: data,
                layerId: layer.id,
                layerType: layer.geoType
              })
              : createPointLayer({
                data: data,
                layerId: layer.id,
                layerType: layer.geoType
              });

          case 'wms':
            return createWmsLayer({
              url: layer.layerUrl,
              layerName: layer.wmsLayerName,
              layerId: layer.id,
              params: layer.params || {}
            });

          case 'wmts':
            // 实现面图层创建逻辑
            console.warn('wmts图层功能尚未实现');
            throw new Error('wmts图层功能尚未实现');

          case 'base':
            this.switchBaseLayer(layer);
            return null;
          case 'model':
            console.log('模型');
            return this.addRiverToMap(this.SelectdRiver)

          default:
            console.error('未知图层类型:', layer.type);
            throw new Error(`未知图层类型: ${layer.type}`);
        }
      } catch (error) {
        console.error(`创建图层 ${layer.id} 失败:`, error);
        throw error;
      }
    },
    addLayerToMap(newLayer, layerConfig) {
      if (!this.map) return;

      // 设置图层基本属性
      newLayer.set('id', layerConfig.id);
      newLayer.set('name', layerConfig.name);
      newLayer.set('type', layerConfig.geoType);

      // 设置图层缩放范围限制
      if (layerConfig.minZoom) newLayer.setMinZoom(layerConfig.minZoom);
      if (layerConfig.maxZoom) newLayer.setMaxZoom(layerConfig.maxZoom);

      // 添加到地图
      this.map.addLayer(newLayer);

      // 记录已加载的图层
      this.loadedLayers[layerConfig.id] = newLayer;

      // 触发图层加载完成事件
      this.$emit('layerLoaded', layerConfig.id);
    },

    removeLayer(layerId) {
      if (!this.map) return;

      // 更新当前图层ID列表
      this.currentLayerIds = this.currentLayerIds.filter(id => id !== layerId);

      // 移除图层
      const layer = this.loadedLayers[layerId];
      if (layer) {
        this.map.removeLayer(layer);
        delete this.loadedLayers[layerId];

        // 触发图层移除事件
        this.$emit('layerRemoved', layerId);
      }
    },
    // 创建基础WMS图层
    createBaseWmsLayer(id, layerName, visible) {
      const layer = createWmsLayer({
        url: wmsBaseUrl,
        layerName: layerName,
        layerId: id,
        params: {
          "format": 'image/png',
          'VERSION': '1.1.1',
          "STYLES": '',
          "LAYERS": layerName,
        }
      });
      layer.set("id", id);
      layer.setVisible(visible);
      return layer;
    },

    // 创建天地图图层
    createTiandituLayers() {
      const layers = [];
      const token = TIANDITU_CONFIG.TOKEN;
      const tileGrid = TIANDITU_CONFIG.TILE_GRID;
      const projection = MAP_CONFIG.PROJECTION;

      // 天地图矢量
      const tianditu_vec = this.createTiandituLayer('tianditu-vec', 'base_tianditu_vec', 'vec_c', 'vec', true);
      const tianditu_cva = this.createTiandituLayer('tianditu-cva', 'base_tianditu_cva', 'cva_c', 'cva', true);

      // 天地图影像
      const tianditu_img = this.createTiandituLayer('tianditu-img', 'base_tianditu_img', 'img_c', 'img', false);
      const tianditu_cia = this.createTiandituLayer('tianditu-cia', 'base_tianditu_cia', 'cia_c', 'cia', false);

      layers.push(tianditu_vec, tianditu_cva, tianditu_img, tianditu_cia);
      return layers;
    },

    // 创建单个天地图图层
    createTiandituLayer(name, id, service, layer, visible) {
      const token = TIANDITU_CONFIG.TOKEN;
      const tileGrid = TIANDITU_CONFIG.TILE_GRID;
      const projection = MAP_CONFIG.PROJECTION;

      const layerInstance = new TileLayer({
        name: name,
        source: new XYZ({
          url: `http://t{0-7}.tianditu.gov.cn/${service}/wmts?SERVICE=WMTS&VERSION=1.0.0&REQUEST=GetTile&LAYER=${layer}&STYLE=default&TILEMATRIXSET=c&FORMAT=tiles&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}&tk=${token}`,
          projection: projection,
          tileGrid: tileGrid
        })
      });

      layerInstance.set("id", id);
      layerInstance.setVisible(visible);
      return layerInstance;
    },

    switchBaseLayer(layer) {
      const baseLayers = ['tianditu-vec', 'tianditu-img'];
      baseLayers.forEach(layerId => {
        const mapLayer = this.getLayerByName(layerId);
        if (mapLayer) mapLayer.setVisible(layerId === layer.id);
      });
    },

    // helper: 根据 name 查找地图图层
    getLayerByName(name) {
      return this.map && this.map.getLayers().getArray().find(l => l.get('name') === name);
    },

    // 弹窗相关方法
    showPopup(featureData, layerId, position) {

      this.popupFeatureData = featureData;
      this.popupLayerId = layerId;
      // this.popupLayerType = layerType;
      this.popupPosition = position;
      this.popupVisible = true;
    },

    closePopup() {

      this.popupFeatureData = {};
      this.popupLayerId = '';
      this.popupLayerType = '';
      this.popupVisible = false;
    },

    // 面板相关方法
    closePanel() {
      this.panelVisible = false;
      this.activePanelLayer = '';
      this.panelTitle = '图层信息';
      this.activePanelLayers = [];
    },
    queryYujingData(dateRange) {
      //console.log("queryYujingData", dateRange)
      getData('yujing', dateRange)
        .then(response => {
          const data = response.data || [];
          removeLayerById(this.map, 'yujing');
          let newLayer = createPointLayer({
            data: data,
            layerId: 'yujing',
            layerType: 'Point'
          });
          this.addLayerToMap(newLayer, {
            id: 'yujing',
            name: 'yujing',
            type: 'Point',
          });
        })
        .catch(error => {
          console.error(`获取预警数据失败:`, error);
        });
    },
    // 切换天地图底图类型（精简实现）
    switchTiandituBaseLayer(type) {
      this.activeBaseLayer = type;
      const ids = {
        vec: 'base_tianditu_vec',
        cva: 'base_tianditu_cva',
        img: 'base_tianditu_img',
        cia: 'base_tianditu_cia',
        base_img: 'base_img',
        base_dlg: 'base_dlg',
      };

      const setVisible = (id, visible) => {
        const layer = this.getLayerById(id);
        if (layer) layer.setVisible(visible);
      };

      if (type === 'image') {
        // 影像图：显示影像和影像注记，隐藏矢量相关图层
        setVisible(ids.vec, false);
        setVisible(ids.cva, false);
        setVisible(ids.img, true);
        setVisible(ids.cia, true);
        setVisible(ids.base_dlg, false);
        setVisible(ids.base_img, true);
      } else {
        // 矢量图（默认）
        setVisible(ids.vec, true);
        setVisible(ids.cva, true);
        setVisible(ids.img, false);
        setVisible(ids.cia, false);
        setVisible(ids.base_dlg, true);
        setVisible(ids.base_img, false);
      }
    },

    /*
    *********************污染源扩散模型**************************************
     */
    // 清理动画计时器
    clearAnimation() {
      if (this.animationTimer) {
        clearTimeout(this.animationTimer);
        this.animationTimer = null;
      }
      // 清空样式缓存以防占用过多内存（下次启动会重新生成）
      this.styleCache = {};
    },

    // 污染颜色配置
    initPollutionColors() {
      this.pollutionColors = chroma.scale(['#00FF00', '#FFFF00', '#FF0000']).mode('lab').colors(20)
    },
    // 添加河流数据，通过名称选择不同geojson文件，生成河流图层，加载至地图
    addRiverToMap(riverName) {
      console.log('===addRiverToMap  添加河流数据 ===');
      // 移除现有的河流图层（如果存在）
      if (this.riverLayer) {
        this.map.removeLayer(this.riverLayer);
      }

      // 根据河流名称构建GeoJSON文件路径
      const geojsonUrl = `/4326/${riverName}.geojson`;

      // 创建矢量源并加载GeoJSON数据
      this.riverLayer = new VectorLayer({
        source: new VectorSource({
          format: new GeoJSON(),
          url: geojsonUrl
        }),
        style: new Style({
          stroke: new Stroke({
            color: '#4A90E2',
            width: 5
          })
        })
      });



      // 将河流图层添加到地图
      this.map.addLayer(this.riverLayer);

      // 监听数据加载完成事件，调整视图以适应河流范围
      this.riverLayer.getSource().once('featuresloadend', () => {
        const extent = this.riverLayer.getSource().getExtent();
        this.map.getView().fit(extent, {
          padding: [50, 50, 50, 50],
          duration: 1000
        });
      });
      return this.riverLayer;
    },
    // 处理位置拾取事件
    onPickLocation() {
      // 启用地图点位拾取模式
      this.isPickingLocation = true;
      // 可以添加视觉提示，告知用户进入拾取模式
      this.$message.info('请点击地图选择污染源位置');

      // 如果有地图实例，可以调用地图的拾取功能
      this.enableLocationPicking();
    },
    enableLocationPicking() {
      // 移除之前可能存在的点击监听器
      if (this.mapClickListener) {
        this.map.un('click', this.mapClickListener);
      }

      // 定义地图点击事件处理函数
      this.mapClickListener = (event) => {
        if (this.isPickingLocation) {
          const coordinates = event.coordinate;
          // 将坐标格式化并设置到侧边栏表单中
          const formattedCoords = `${coordinates[0].toFixed(6)}, ${coordinates[1].toFixed(6)}`;
          // 存储拾取的坐标
          this.pickedCoordinates = formattedCoords;
          this.pollutedLocation = coordinates;
          this.addPointToMap(coordinates)
          // 退出拾取模式
          this.isPickingLocation = false;

          // 显示成功消息
          this.$message.success(`位置已设置: ${formattedCoords}`);

          // 移除点击监听器
          this.map.un('click', this.mapClickListener);
          this.mapClickListener = null;
        }
      };
      this.map.on('click', this.mapClickListener);
    },
    // 在 methods 中添加以下方法
    addPointToMap(coordinates) {
      let markerSource = new VectorSource();
      if (this.markerLayer) {
        this.map.removeLayer(this.markerLayer);
      }
      this.markerLayer = new VectorLayer({
        source: markerSource,
        style: new Style({
          image: new Circle({
            radius: 6,
            fill: new Fill({
              color: '#FF0000'
            }),
            stroke: new Stroke({
              color: '#FFFFFF',
              width: 2
            })
          })
        })
      });
      this.map.addLayer(this.markerLayer);

      // 创建新的点要素
      const pointFeature = new Feature({
        geometry: new Point(coordinates)
      });

      // 设置点要素的样式

      pointFeature.setStyle(new Style({
        image: new Circle({
          radius: 6,
          fill: new Fill({
            color: '#FF0000'
          }),
          stroke: new Stroke({
            color: '#FFFFFF',
            width: 2
          })
        })
      }));


      // 将点要素添加到源中
      markerSource.addFeature(pointFeature);

      return pointFeature;
    },
    cancelLocationPicking() {
      this.isPickingLocation = false;
      if (this.mapClickListener) {
        this.map.un('click', this.mapClickListener);
        this.mapClickListener = null;
      }
      this.$message.info('位置拾取已取消');
    },

    // ==================== 查找污染源所在河段 ====================
    findSourceSegment(pos, features) {
      const point = pos;
      let minDist = Infinity;
      let closestIdx = -1;

      features.forEach((feat, idx) => {
        const geom = feat.getGeometry();
        const closestPoint = geom.getClosestPoint(point);
        const dx = closestPoint[0] - point[0];
        const dy = closestPoint[1] - point[1];
        const dist = Math.sqrt(dx * dx + dy * dy);
        if (dist < minDist) {
          minDist = dist;
          closestIdx = feat.getProperties()['index'];
        }
      });
      return { index: closestIdx, distance: minDist };
    },

    // ====================一维水动力模型 ====================
    handleStartSimulation(dataForm) {
      // 优化说明：将原来一次性计算全部结果改为分步模拟并动画展示，避免阻塞线程
      try {
        // 清理之前的动画
        this.clearAnimation();

        // 基础检查
        if (!this.riverLayer) {
          this.$message.warning('请先加载河流图层');
          return;
        }

        // 步骤一：获取污染源所在河段索引
        const features = this.riverLayer.getSource().getFeatures();
        const sourceInfo = this.findSourceSegment(this.pollutedLocation, features);
        const startIndex = sourceInfo.index;

        if (startIndex === -1) {
          this.$message.error('未找到污染源所在河段，请重新选择位置');
          return;
        }

        // 步骤二：获取参数并规范化
        this.emission = Number(dataForm.emission) || this.emission; // kg
        this.pollution_rate = Number(dataForm.pollution_rate) || this.pollution_rate; // kg/s
        this.total_time = Number(dataForm.total_time) * 3600 || this.total_time; // s
        this.flow_speed = Number(dataForm.flow_speed) || this.flow_speed; // m/s
        this.timestep = (Number(dataForm.timestep) || (this.timestep / 60)) * 60; // 转为秒

        // 计算释放时间与实际模拟时间
        const releaseTime = this.emission / this.pollution_rate; // seconds
        const actualSimulationTime = Math.min(releaseTime, this.total_time);

        // 预处理特征映射并初始化污染属性
        const featureMap = new Map();
        features.forEach(feature => {
          const index = feature.getProperties()['index'];
          featureMap.set(index, feature);
          feature.set('pollution_concentration', 0);
        });

        // 初始化组件级动画状态，便于外部 pause/resume/reset 控制
        this.animationFeatures = features;
        this.animationFeatureMap = featureMap;
        this.animationStartIndex = startIndex;
        this.animationMaxAffectedIndex = startIndex - 1;
        this.animationReleaseTime = releaseTime;
        this.animationTimeStepSeconds = this.timestep;
        this.animationPollutionRate = this.pollution_rate;
        this.animationFlowSpeed = this.flow_speed;
        this.animationTotalSteps = Math.max(1, Math.floor(actualSimulationTime / this.timestep));
        this.animationCurrentStep = 0;
        // 存储总的模拟秒数，供进度计算使用
        this.animationTotalSimSeconds = actualSimulationTime;
        // 重置当前时间（秒），供侧边栏进度条使用
        this.currentTime = 0;
        this.isAnimating = true;
        this.isPaused = false;

        // 启动动画循环（分步）
        this.runAnimationStep();

      } catch (error) {
        console.error('模拟过程中出现错误：', error);
        this.$message.error('模拟失败，请查看控制台了解详情。');
      }
    },
    // 运行动画的单步逻辑（支持 pause/resume）
    runAnimationStep() {
      if (!this.isAnimating) return;
      if (this.isPaused) return;

      // 增加步数
      this.animationCurrentStep += 1;
      const currentTime = this.animationCurrentStep * this.animationTimeStepSeconds; // s
      // 同步当前时间到组件状态，供侧边栏进度条显示
      this.currentTime = currentTime;
      // 计算并设置当前进度百分比（优先用于更精确的进度显示）
      if (this.animationTotalSimSeconds > 0) {
        const pct = Math.round(Math.min(100, (currentTime / this.animationTotalSimSeconds) * 100));
        this.animationProgressPercent = pct;
        // 通过事件向外发出进度，可被外部监听
        // try { this.$emit('simulation-progress', pct); } catch (e) { }
      }

      // 计算当前步新增污染质量
      const currentPollutionMass = currentTime <= this.animationReleaseTime ? this.animationPollutionRate * this.animationTimeStepSeconds : 0;

      // 传播到的河段上限
      const features = this.animationFeatures || [];
      const featureMap = this.animationFeatureMap || new Map();
      const startIndex = this.animationStartIndex || 0;

      const currentMaxSegmentIndex = Math.min(
        Math.floor(startIndex + this.animationFlowSpeed * currentTime),
        features.length - 1
      );

      // 只处理新影响到的河段
      for (let i = this.animationMaxAffectedIndex + 1; i <= currentMaxSegmentIndex; i++) {
        const feature = featureMap.get(i);
        if (!feature) continue;

        const distanceFromSource = i - startIndex;
        const decayFactor = Math.exp(-distanceFromSource * 0.001);
        const concentrationIncrement = currentPollutionMass * decayFactor;
        const curr = feature.get('pollution_concentration') || 0;
        feature.set('pollution_concentration', curr + concentrationIncrement);
      }

      this.animationMaxAffectedIndex = currentMaxSegmentIndex;

      // 计算当前最大浓度，用于颜色映射
      let currentMax = 0;
      features.forEach(f => {
        const c = f.get('pollution_concentration') || 0;
        if (c > currentMax) currentMax = c;
      });

      // 更新样式
      features.forEach(feature => {
        const concentration = feature.get('pollution_concentration') || 0;
        let strokeColor = '#4A90E2';
        if (concentration > 0 && currentMax > 0) {
          const ratio = Math.min(1, concentration / currentMax);
          const colorIndex = Math.floor(ratio * (this.pollutionColors.length - 1));
          strokeColor = this.pollutionColors[colorIndex];
        }

        let style = this.styleCache[strokeColor];
        if (!style) {
          style = new Style({
            stroke: new Stroke({
              color: strokeColor,
              width: 5
            })
          });
          this.styleCache[strokeColor] = style;
        }
        feature.setStyle(style);
      });

      // 判断是否继续
      if (this.animationCurrentStep < this.animationTotalSteps && (currentPollutionMass > 0 || this.animationMaxAffectedIndex < features.length - 1)) {
        this.animationTimer = setTimeout(() => this.runAnimationStep(), this.animationStepInterval);
      } else {
        this.animationTimer = null;
        this.isAnimating = false;
        // 确保 currentTime 达到最终时间
        this.currentTime = Math.min(this.animationReleaseTime, this.animationTotalSimSeconds);
        // 最终进度设为 100%
        this.animationProgressPercent = 100;
        // try { this.$emit('simulation-progress', 100); } catch (e) { }
        this.$message.success('模拟完成');
      }
    },

    // 暂停动画
    pauseSimulation() {
      if (!this.isAnimating) return;
      this.isPaused = true;
      if (this.animationTimer) {
        clearTimeout(this.animationTimer);
        this.animationTimer = null;
      }
      this.$message.info('模拟已暂停');
    },

    // 继续动画
    resumeSimulation() {
      if (!this.isAnimating) return;
      if (!this.isPaused) return;
      this.isPaused = false;
      this.$message.info('继续模拟');
      // 继续运行下一步
      if (!this.animationTimer) {
        this.animationTimer = setTimeout(() => this.runAnimationStep(), this.animationStepInterval);
      }
    },

    // 重置模拟
    resetSimulation() {
      // 停止并清理动画
      this.clearAnimation();
      this.isAnimating = false;
      this.isPaused = false;
      this.animationCurrentStep = 0;
      this.animationTotalSteps = 0;
      this.animationFeatureMap = null;
      this.animationStartIndex = null;
      this.animationMaxAffectedIndex = null;
      this.animationReleaseTime = 0;
      this.animationFeatures = null;

      // 重置显示的当前时间
      this.currentTime = 0;

      // 将河段样式和污染浓度重置为初始状态
      if (this.riverLayer && this.riverLayer.getSource()) {
        const features = this.riverLayer.getSource().getFeatures();
        features.forEach(feature => {
          feature.set('pollution_concentration', 0);
          feature.setStyle(new Style({
            stroke: new Stroke({
              color: '#4A90E2',
              width: 5
            })
          }));
        });
      }
      // this.$message.info('模拟已重置');
    },
  }
};
</script>

<style lang="scss" scoped>
@import "~@/style/variables.scss";

.map-container {
  width: 100%;
  height: calc(100vh - 105px);
}

.map-controls {
  position: absolute;
  bottom: 20px;
  left: 20px;
  z-index: 1000;
}

.base-layer-switcher {
  display: flex;
  background: rgba(255, 255, 255, 0.8);
  border-radius: 4px;
  padding: 4px;
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.2);

  .control-btn {
    padding: 6px 12px;
    margin: 0;
    border: none;
    background: transparent;
    cursor: pointer;
    font-size: 12px;
    border-radius: 2px;
    transition: all 0.3s;

    &:hover {
      background: rgba(0, 0, 0, 0.1);
    }

    &.active {
      background: $base-blue-background; // reuse project variable
      color: white;
    }
  }
}
</style>